---
title: Deploying your site with Git
date: 2012-06-10
layout: post
categories:
- Blog
comments: true
tags: []
description: "How to setup git source control to deploy a web site.  This works great for static web sites such as Jekyll or Pretzel based sites.  I am using bluehost but should work with other shared hosting services."
---
I have been using [Git][1] quite a bit lately, from my work on the CodePlex team, along with several personal projects.  Git is pretty powerful, and given its distributed nature, it has some pretty cool capabilities one of them is to push source code from one location to another - "developer ftp".  When I was creating my [updated blog][3], I really wanted to find a nice way to use Git to push changes to my site onto the production web server.
<!--more-->
Since I am using [Pretzel][2] to generate a static version of this site on my desktop, I just needed the ability to moving the contents of the output folder (_site) onto the my public web server hosted at Bluehost.  This would work the same way if I was using Jekyll or any other static site generator. I could FTP the files between machines, but I liked the idea of having another remote location that had a versioned copy of my site.  Additionally, if something went wrong, since the site was stored with Git, I could always revert to a previous working version.

The flow goes like this:

* Make a change to blog source or create a blog post
* Pretzel Bake or Jekyll --server
* Commit the changes within the _site folder 
* Git Push to Remote setup within Bluehost
* Within Remote, post-commit trigger does a pull into the www root

With this flow, only changed items are transfered, and git handles the compression and decompression on either end. 

####Configuring Git on bluehost####
Getting Git running on bluehost is pretty simple, I doubt that bluehost really supports this scenario but hey it works.  For me this is just a small repository that handles my blog, large source repositories go on CodePlex.  First you need to request SSH access from bluehost, go to the bluehost dashboard and select Manage SSH Access.  Once you have SSH access use something like Putty to SSH into your account.

1. Create source directory to store git tarball
	<pre><code class="terminal">
myuser@markgroves.us [~/]# mkdir src
myuser@markgroves.us [~/]# cd src
</code></pre>
2. Download latest source
	<pre><code class="terminal">
myuser@markgroves.us [~/src]# wget http://git-core.googlecode.com/files/git-1.7.11.rc2.tar.gz
myuser@markgroves.us [~/src]# tar xvfz git-1.7.11.rc2.tar.gz
</code></pre>
3. Build Git
	<pre><code class="terminal">
myuser@markgroves.us [~/src]# cd git-1.7.11.rc2
myuser@markgroves.us [~/src/git-1.7.11.rc2]# ./configure --prefix=$HOME
myuser@markgroves.us [~/src/git-1.7.11.rc2]# make SHELL="/bin/bash" install
</code></pre>
4. Setup Git Remote to store site
	<pre><code class="terminal">
myuser@markgroves.us [~]# export PATH=$PATH:$HOME/bin
myuser@markgroves.us [~]# mkdir -p ~/git/yoursitename.git
myuser@markgroves.us [~]# cd ~/git/yoursitename.git
myuser@markgroves.us [~/git/yoursitename.git]# git --bare init
</code></pre>

Now you have a bare git repository setup on bluehost.  But a bare git repository won't do much, we need a expanded working directory within the www root.  Since we are going to Git Push to the bare repository we will setup a post-receive hook to do a pull into the working directory.

1. Setup working directory
	<pre><code class="terminal">
myuser@markgroves.us [~]# cd www/
myuser@markgroves.us [~/www]# git clone ~/git/yoursitename.git/ .
</code></pre>

2. Setup the post receive hook
>Create a file named post-receive and place it in ~/git/yoursitename.git/hooks the contents should look like:
	<pre><code class="terminal">
GIT\_REPO=$HOME/git/yoursitename.git
TMP\_GIT\_CLONE=$HOME/tmp/yoursitename
PUBLIC\_WWW=$HOME/www
\#!/bin/bash
cd $PUBLIC\_WWW || exit
unset GIT\_DIR
git pull
exec git-update-server-info
exit
</code></pre>
>The first three lines are just setting up a few default folders parameters.  Then we are going to change into the www directory and to a pull.  The unset GIT\_DIR is necessary since there is a default setting that won't respect the directory while you are in the bare git repository.  The exec git-update-server-info command resets the defaults.
>
>Make sure you set the post-receive hook file to be executable: **chmod +x post-receive**


So now each time you do a git push into the bare repository, the post-receive hook fires and does a pull into the www folder, updating the site.

####Setup your local repository####
Both Pretzel and Jekyll, by default, are configured to output the "compiled" site into a \_site folder.  This folder contains a complete folder structure that will working within your www folder on your web server.  Since this is the folder that I want to push to bluehost I needed to do a little git trickery to not push the parent folders.

1. Add \_site to the git ignore list
	<pre><code class="terminal">
\#site build output
\_site/
</code></pre>
create a .gitignore file within your base site folder, this assumes you have your site within git for development

2. Git initiate the \_site folder to setup a new git repository
	<pre><code class="terminal">
D:\development\markgroves.us\\\_site>  git init
D:\development\markgroves.us\\\_site [master]> git add .
D:\development\markgroves.us\\\_site [master]> git commit -m 'initial commit of site'
</code></pre>

3. Setup the remote to the bluehost remote git repository
	<pre><code class="terminal">
D:\development\markgroves.us\\\_site [master]> git remote add deploy myuser@mysitename:~/git/mysitename.git
</code></pre>

4. Deploy changes to the server
	<pre><code class="terminal">
D:\development\markgroves.us\\\_site [master]> git push deploy master
</code></pre>

####Conclusion####
Now each time I do a git push the remote bare repository will get updated, and the post-receive hook will fire updating the www folder and the site.  For me this is great, keep everything versioned using git, and with just one additional commant (git push) I get the my site updated in seconds.

[1]: http://git-scm.com
[2]: http://code52.org/pretzel/
[3]: /2012/06/04/dropping-wordpress-for-pretzel.html
